import MSLogger
from datetime import timedelta, datetime
from time import time
import shelve
import cPickle

TIME_FORMAT_MAGIC = '%d%m%Y_%H%M%S'     #time format descriptor used in magic db
TIME_FORMAT_PCN = '%Y-%m-%d %H:%M:%S'   #time format descriptor used in pcn db
TIME_FORMAT_CESAR = '%d.%m.%Y %H:%M:%S'
MS_MSGID_TO_CONTACTID = {
                       '11':'1201',
                       '12':'1201',
                       '13':'1201',
                       '20':'1201',
                       '21':'1201',
                       '22':'1201'
}

class MSEvent:
    def __init__(self):
        #event internal identificator
        self.eventId = 0
        #event internal type
        self.eventType = 0
        #object owner of the event - who generated
        self.objectId = 0
        #user owner of the event - who this object belongs to
        self.userOwnerId = 0
        #user writer of the event - who put into DB
        self.userWriterId = 0
        #when event has been received
        self.eventReceiveTime = datetime.fromtimestamp(time())
        #when event has been generated
        self.eventGenerateTime = self.eventReceiveTime

#STATIC EVENT DATA
        #does event have static data
        self.hasStatic = False
        #event type in ContactId's notation
        self.contactIdType = 0

#MOBILE EVENT DATA
        #does event have gps coordinates
        self.hasMobile = False
        #TBD describe coordinate notation and speed measurements
        self.GPSLatitude = 0.0
        self.GPSLongitude = 0.0
        self.GPSSpeed = 0.0

    def __hash__(self):
        return self.eventId

    def __cmp__(self, y):
        if y == None:
            return 1
        if self.eventGenerateTime > y.eventGenerateTime:
            return 1
        if self.eventGenerateTime < y.eventGenerateTime:
            return -1
        if self.eventId > y.eventId:
            return 1
        if self.eventId < y.eventId:
            return -1
        return 0

    def fromPGSM(self, rawEvent):
        global MS_MSGID_TO_CONTACTID
        global TIME_FORMAT_MAGIC
        self.hasStatic = True
        self.contactIdType = MS_MSGID_TO_CONTACTID.get(rawEvent['type'], None)
        if self.contactIdType == None:
            raise Exception('unknown PGSM type %s' % (str(rawEvent['type'])))
        self.eventGenerateTime = datetime.strptime(rawEvent['datetime'], TIME_FORMAT_MAGIC)
        self.eventId = rawEvent['eventInternalId']

    def fromContactId(self, rawEvent):
        self.hasStatic = True
        cid = rawEvent['value']
        contactId_Object = cid[2:6]
        contactId_Group = cid[6:7]
        contactId_Type = cid[7:10]
        self.contactIdType = "%s%s" % (contactId_Type, contactId_Group)
        self.objectId = int(contactId_Object)
        self.eventGenerateTime = datetime.strptime(rawEvent['date'], TIME_FORMAT_MAGIC)
        self.eventId = rawEvent['eventInternalId']

    def fromGPSPoint(self, rawEvent):
        self.hasMobile = True
        #we should transfer LAT and LON
        #LAT
        ddd = float(rawEvent['lat'])
        dd = int(ddd)
        mm = int(float((ddd - dd)*60))
        ss = str(((ddd - dd)*60 - mm)*60)
        mm = str(mm)
        if (len(mm)) < 2:
            mm = '0%s' % (mm[0])
        dd = str(dd)
        self.GPSLatitude = dd[0:2] + mm[0:2] + '.' + ss.replace('.','')[0:4]
        #LON
        ddd = float(rawEvent['lon'])
        dd = int(ddd)
        mm = int(float((ddd - dd)*60))
        ss = str(((ddd - dd)*60 - mm)*60)
        mm = str(mm)
        if (len(mm)) < 2:
            mm = '0%s' % (mm[0])
        dd = str(dd)
        self.GPSLongitude = dd[0:2] + mm[0:2] + '.' + ss.replace('.','')[0:4]
        self.GPSSpeed = rawEvent['speed']
        self.eventGenerateTime = datetime.strptime(rawEvent['date'], TIME_FORMAT_MAGIC)
        self.eventId = rawEvent['eventInternalId']


class MSObject:
    def __init__(self, ObjID):
        #unified object id
        self.objectId = ObjID
        #human readable object name
        self.objectName = ''
        #object skey to the MS API
        self.objectSkey = ''
        #does object have pgsm static data
        self.isStatic = False
        #does object have pgsm contact id static data
        self.isContactId = False
        #does object have gps mobile data
        self.isMobile = False
        #time range for an object to alarm offline state
        self.offlineCritical = timedelta(0, 180)
        self.offlineState = False

        #processeability parameters
        #storage root
        self.storageRoot = None
        #cached disk storage for recent(couple of days) events
        self.eventStorage = None
        #memory event queue of new events
        self.pendingEvents = []
        self.pendingEventsDone = True
        self.lastEvent = None

    def __hash__(self):
        return self.objectId
    def __cmp__(self, y):
        if self.objectId > y.objectId:
            return 1
        if self.objectId < y.objectId:
            return -1
        return 0

    def openEventStorage(self):
        try:
            if self.eventStorage == None and self.storageRoot != None:
                fname = '%s/recent.%d' % (self.storageRoot, self.objectId)
                self.eventStorage = shelve.open(fname)
        except (Exception), err:
            MSLogger.logError('unable to open eventStorage(%s) with exception: %s' % (str(self.objectId), str(err)))
            self.eventStorage = None


    def closeEventStorage(self):
        try:
            if self.eventStorage != None:
                self.eventStorage.close()
                self.eventStorage = None
        except (Exception), err:
            MSLogger.logError('unable to close eventStorage(%s) with exception: %s' % (str(self.objectId), str(err)))

    def processEvent(self, Event):
        self.lastEvent = Event
        self.pendingEvents.append(Event)

        if self.eventStorage != None:
            self.eventStorage[str(Event.eventGenerateTime) + ' ' + str(Event.eventId)] = Event
        elif self.storageRoot != None:
            self.openEventStorage()

